package cn.lg.soar.core.util;

import cn.lg.soar.common.data.ZSet;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;

import java.util.function.Consumer;

/**
 * 应用订阅器
 * @author luguoxiang
 * @date 2022/3/31
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Lazy(false)
@Order
public class SoarSubscriber  implements ApplicationRunner, SmartLifecycle {

    private final static ZSet<Consumer<ApplicationContext>> START_LISTENERS = new ZSet<>();
    private final static ZSet<Consumer<ApplicationContext>> STOP_LISTENERS = new ZSet<>();
    private static ZSet<Consumer<ApplicationContext>> initListeners = new ZSet<>();
    private static ZSet<Consumer<ApplicationContext>> runnerListeners = new ZSet<>();
    private static ApplicationContext applicationContext;

    private boolean running;

    /**
     * spring初始化时触发(只触发一次)
     * @param consumer
     */
    public static void subscribeInit(Consumer<ApplicationContext> consumer, int order) {
        if (applicationContext == null) {
            initListeners.add(consumer, order);
        } else {
            consumer.accept(applicationContext);
        }
    }

    public static void subscribeInit(Consumer<ApplicationContext> consumer) {
        subscribeInit(consumer, 0);
    }

    /**
     * spring启动完成后触发
     * @param consumer
     * @param order
     */
    public static void subscribeRunner(Consumer<ApplicationContext> consumer, int order) {
        if (runnerListeners != null) {
            runnerListeners.add(consumer, order);
        } else {
            consumer.accept(applicationContext);
        }
    }

    public static void subscribeRunner(Consumer<ApplicationContext> consumer) {
        subscribeRunner(consumer, 0);
    }

    /**
     * spring启动时触发
     * @param consumer
     */
    public static void subscribeStart(Consumer<ApplicationContext> consumer, int order) {
        START_LISTENERS.add(consumer, order);
        if (applicationContext != null) {
            consumer.accept(applicationContext);
        }
    }

    public static void subscribeStart(Consumer<ApplicationContext> consumer) {
        subscribeStart(consumer, 0);
    }

    /**
     * spring停止时触发
     * @param consumer
     */
    public static void subscribeStop(Consumer<ApplicationContext> consumer, int order) {
        STOP_LISTENERS.add(consumer, order);
        if (applicationContext != null) {
            consumer.accept(applicationContext);
        }
    }

    public static void subscribeStop(Consumer<ApplicationContext> consumer) {
        subscribeStop(consumer, 0);
    }

    public SoarSubscriber(ApplicationContext applicationContext) {
        SoarSubscriber.applicationContext = applicationContext;
        initListeners.forEach(x -> x.accept(applicationContext));
        initListeners.clear();
        initListeners = null;
    }

    @Override
    public void run(ApplicationArguments args) {
        ZSet<Consumer<ApplicationContext>> consumers = runnerListeners;
        runnerListeners = null;
        consumers.forEach(x -> x.accept(applicationContext));
        consumers.clear();
    }

    @Override
    public void start() {
        running = true;
        START_LISTENERS.forEach(x -> x.accept(applicationContext));
    }

    @Override
    public void stop() {
        running = false;
        STOP_LISTENERS.forEach(x -> x.accept(applicationContext));
    }

    @Override
    public boolean isRunning() {
        return running;
    }

}
